package com.xteam.ecsystem.utils.jmagick;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.log4j.Logger;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

@SuppressWarnings("unchecked")
public class ImageUtil {

	private static final Logger logger = Logger.getLogger(ImageUtil.class);
	private static Component component = new Canvas();

	private static String[] imageFormatArray = new String[] { ".jpg", ".jpeg",
			".gif", ".png", ".bmp" };

	/**
	 * 查看图像I/O库所支持的图像格式有哪些格式
	 */
	public void listFormat() {
		String readerMIMETypes[] = ImageIO.getReaderMIMETypes();
		String writerMIMETypes[] = ImageIO.getWriterMIMETypes();
		if (logger.isInfoEnabled()) {
			logger.info("ReaderMIMETypes:" + Arrays.asList(readerMIMETypes));
			logger.info("WriterMIMETypes:" + Arrays.asList(writerMIMETypes));
		}
	}

	/**
	 * 将目录下的所有图像进行放大缩小
	 * 
	 * @param strDir
	 *            图像的目录
	 * @param zoomRatio
	 *            放大缩小的倍率
	 * @param rebuild
	 *            是否重新创建，即已经存在的图像是否覆盖重建
	 * @throws Exception
	 *             Exception
	 */
	public void zoom1(String fileName, String fileNameTarget, double zoomRatio,
			boolean rebuild) throws Exception {
		File fileDir = new File(fileName);
		if (!fileDir.exists()) {
			logger.warn("Not exist:" + fileName);
			return;
		}
		String fileShortName = fileDir.getName();
		if (isZoomAble(fileShortName)) {
			if (!new File(fileNameTarget).exists() || rebuild) {
				try {
					createZoomSizeImage(fileName, fileNameTarget, zoomRatio);
				} catch (Exception e) {
					logger.error("createZoomSizeImage Error:" + fileName, e);
				}
			}
		}

	}

	/**
	 * 将目录下的所有图像进行放大缩小
	 * 
	 * @param strDir
	 *            图像的目录
	 * @param zoomRatio
	 *            放大缩小的倍率
	 * @param rebuild
	 *            是否重新创建，即已经存在的图像是否覆盖重建
	 * @throws Exception
	 *             Exception
	 */
	public void zoom(String strDir, double zoomRatio, boolean rebuild)
			throws Exception {
		File fileDir = new File(strDir);
		if (!fileDir.exists()) {
			logger.warn("Not exist:" + strDir);
			return;
		}
		String dirTarget = strDir + "/Zoom" + zoomRatio;
		File fileTarget = new File(dirTarget);
		if (!fileTarget.exists()) {
			fileTarget.mkdir();
		}
		File[] files = fileDir.listFiles();
		StringBuilder stringBuilder;
		for (File file : files) {
			String fileFullName = file.getCanonicalPath();
			String fileShortName = file.getName();
			if (!new File(fileFullName).isDirectory())// 排除二级目录，如果想就再递归一次，这里省略
			{
				if (isZoomAble(fileShortName)) {
					if (logger.isInfoEnabled()) {
						logger.info("Begin Zoom:" + fileFullName);
					}
					stringBuilder = new StringBuilder();
					stringBuilder.append(dirTarget).append("/").append(
							fileShortName);
					if (!new File(stringBuilder.toString()).exists() || rebuild) {
						try {
							createZoomSizeImage(fileFullName, stringBuilder
									.toString(), zoomRatio);
						} catch (Exception e) {
							logger.error("createZoomSizeImage Error:"
									+ fileFullName, e);
						}
					}
					if (logger.isInfoEnabled()) {
						logger.info("End Zoom:" + fileFullName);
					}
				} else {
					logger.warn("Can't Zoom:" + fileFullName);
				}
			}
		}
	}

	/**
	 * 校验图像文件的格式是否可以进行缩放
	 * 
	 * @param fileName
	 *            fileName
	 * @return boolean iszoom able
	 */
	public boolean isZoomAble(String fileName) {
		boolean result = false;
		for (String imageFormat : imageFormatArray) {
			if (fileName.toLowerCase().lastIndexOf(imageFormat) == (fileName
					.length() - imageFormat.length())) {
				result = true;
				break;
			}
		}
		return result;
	}

	/**
	 * 按比例进行放大缩小图像，zoomRatio = 1为原大，zoomRatio > 1为放大，zoomRatio < 1 为缩小
	 * 
	 * @param fileName
	 *            source file name
	 * @param fileNameTarget
	 *            target file name
	 * @param zoomRatio
	 *            zoom ratio
	 * @throws Exception
	 *             exception
	 */
	public void createZoomSizeImage(String fileName, String fileNameTarget,
			double zoomRatio) throws Exception {
		Image image = ImageIO.read(new File(fileName));
		int width = new Double(image.getWidth(null) * zoomRatio).intValue();
		int height = new Double(image.getHeight(null) * zoomRatio).intValue();
		AreaAveragingScaleFilter areaAveragingScaleFilter = new AreaAveragingScaleFilter(
				width, height);
		FilteredImageSource filteredImageSource = new FilteredImageSource(image
				.getSource(), areaAveragingScaleFilter);
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_3BYTE_BGR);
		Graphics graphics = bufferedImage.createGraphics();
		graphics.drawImage(component.createImage(filteredImageSource), 0, 0,
				null);
		ImageIO.write(bufferedImage, "JPEG", new File(fileNameTarget));
	}

	/**
	 * 将目录下的所有图像进行放大缩小
	 * 
	 * @param strDir
	 *            图像的目录
	 * @param picHeight，picWidth
	 *            图片高，宽
	 * @param rebuild
	 *            是否重新创建，即已经存在的图像是否覆盖重建
	 * @throws Exception
	 *             Exception
	 */
	public void zoomByWidthAndHeight(String fileName, String fileNameTarget,
			double picHeight, double picWidth, boolean rebuild)
			throws Exception {
		File fileDir = new File(fileName);
		if (!fileDir.exists()) {
			logger.warn("Not exist:" + fileName);
			return;
		}
		String fileShortName = fileDir.getName();
		if (isZoomAble(fileShortName)) {
			if (!new File(fileNameTarget).exists() || rebuild) {
				try {
					createZoomImageBywh(fileName, fileNameTarget, picHeight,
							picWidth);
				} catch (Exception e) {
					logger.error("createZoomSizeImage Error:" + fileName, e);
				}
			}
		}

	}
	/**
	 * 
	 * 根据设定的高和宽改变图片大小，生成改变后的图片
	 * @param fileName
	 * @param fileNameTarget
	 * @param picHeight
	 * @param picWidth
	 * @throws IOException
	 */
	private void createZoomImageBywh(String fileName, String fileNameTarget,
			double picHeight, double picWidth) throws IOException {
		Image image = ImageIO.read(new File(fileName));
		int width = new Double(picWidth).intValue();
		int height = new Double(picHeight).intValue();
		AreaAveragingScaleFilter areaAveragingScaleFilter = new AreaAveragingScaleFilter(
				width, height);
		FilteredImageSource filteredImageSource = new FilteredImageSource(image
				.getSource(), areaAveragingScaleFilter);
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_3BYTE_BGR);
		Graphics graphics = bufferedImage.createGraphics();
		graphics.drawImage(component.createImage(filteredImageSource), 0, 0,
				null);
		ImageIO.write(bufferedImage, "JPEG", new File(fileNameTarget));
	}

	public void cropImage(String fileName, String fileNameTarget, int x, int y,
			int w, int h) throws Exception {
		Image sourceImage = ImageIO.read(new File(fileName));

		ImageFilter cropFilter = new CropImageFilter(x, y, w, h);// 四个参数分别为图像起点坐标和宽高，即CropImageFilter(int
		// x,int
		// y,int
		// width,int
		// height)，详细情况请参考API
		FilteredImageSource filteredImageSource = new FilteredImageSource(
				sourceImage.getSource(), cropFilter);
		BufferedImage bufferedImage = new BufferedImage(w, h,
				BufferedImage.TYPE_3BYTE_BGR);
		Graphics graphics = bufferedImage.createGraphics();
		graphics.drawImage(component.createImage(filteredImageSource), 0, 0,
				null);
		ImageIO.write(bufferedImage, "JPEG", new File(fileNameTarget));
	}

	public static String getPressImgPath() {
		return "/template/data/util/shuiyin.gif";
	}

	/**
	 * 把图片印刷到图片上
	 * 
	 * @param pressImg --
	 *            水印文件
	 * @param targetImg --
	 *            目标文件
	 * @param x --
	 *            偏移量x
	 * @param y --
	 *            偏移量y
	 */
	public static void pressImage(String pressImg, String targetImg, int x,
			int y) {
		try {
			File _file = new File(targetImg);
			Image src = ImageIO.read(_file);
			int wideth = src.getWidth(null);
			int height = src.getHeight(null);
			BufferedImage image = new BufferedImage(wideth, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics g = image.createGraphics();
			g.drawImage(src, 0, 0, wideth, height, null);

			// 水印文件
			File _filebiao = new File(pressImg);
			Image src_biao = ImageIO.read(_filebiao);
			int wideth_biao = src_biao.getWidth(null);
			int height_biao = src_biao.getHeight(null);
			g.drawImage(src_biao, wideth - wideth_biao - x, height
					- height_biao - y, wideth_biao, height_biao, null);
			// /
			g.dispose();
			FileOutputStream out = new FileOutputStream(targetImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(image);
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 打印文字水印图片
	 * 
	 * @param pressText
	 *            --文字
	 * @param targetImg --
	 *            目标图片
	 * @param fontName --
	 *            字体名
	 * @param fontStyle --
	 *            字体样式
	 * @param color --
	 *            字体颜色
	 * @param fontSize --
	 *            字体大小
	 * @param x --
	 *            偏移量x
	 * @param y --
	 *            偏移量y
	 */

	public static void pressText(String pressText, String targetImg,
			String fontName, int fontStyle, String color, int fontSize, int x,
			int y) {
		try {
			File _file = new File(targetImg);
			Image src = ImageIO.read(_file);
			int wideth = src.getWidth(null);
			int height = src.getHeight(null);
			BufferedImage image = new BufferedImage(wideth, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics graphics = image.createGraphics();
			graphics.drawImage(src, 0, 0, wideth, height, null);
			// String s="www.qhd.com.cn";
			int r = Integer.parseInt(color.substring(0, 2), 16);
			int g = Integer.parseInt(color.substring(2, 4), 16);
			int b = Integer.parseInt(color.substring(4), 16);

			graphics.setColor(new Color(r, g, b));
			graphics.setFont(new Font(fontName, fontStyle, fontSize));

			graphics.drawString(pressText, wideth - fontSize - x, height
					- fontSize / 2 - y);
			graphics.dispose();
			FileOutputStream out = new FileOutputStream(targetImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(image);
			out.close();
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	/**
	 * 读取GIF文件，并进行缩放，存放于BufferedImage数组中
	 * 
	 * @param inputFileName
	 *            source image file
	 * @param zoomRatio
	 *            zoom ratio > 1 zoom in; < 1 zoom out;
	 * @return BufferedImage Array
	 * @throws IOException
	 *             IOException
	 */
	public BufferedImage[] readGifFile(String inputFileName, double zoomRatio)
			throws IOException {
		Iterator imageReaders = ImageIO.getImageReadersBySuffix("GIF");
		if (!imageReaders.hasNext()) {
			throw new IOException("no ImageReaders for GIF");
		}
		ImageReader imageReader = (ImageReader) imageReaders.next();
		File file = new File(inputFileName);
		if (!file.exists()) {
			throw new IOException("no file: " + file.getName());
		}
		imageReader.setInput(ImageIO.createImageInputStream(file));
		ArrayList<BufferedImage> images = new ArrayList<BufferedImage>();
		for (int i = 0; true; ++i) {
			try {
				Image image = imageReader.read(i);
				int width = new Double(image.getWidth(null) * zoomRatio)
						.intValue();
				int height = new Double(image.getHeight(null) * zoomRatio)
						.intValue();
				if (width > 0 && height > 0) {
					AreaAveragingScaleFilter areaAveragingScaleFilter = new AreaAveragingScaleFilter(
							width, height);
					FilteredImageSource filteredImageSource = new FilteredImageSource(
							image.getSource(), areaAveragingScaleFilter);
					BufferedImage bufferedImage = new BufferedImage(width,
							height, BufferedImage.TYPE_3BYTE_BGR);
					Graphics graphics = bufferedImage.createGraphics();
					graphics.drawImage(component
							.createImage(filteredImageSource), 0, 0, null);
					images.add(bufferedImage);
				}
			} catch (IndexOutOfBoundsException e) {
				break;
			}
		}
		return images.toArray(new BufferedImage[images.size()]);
	}

	/**
	 * 根据BufferedImage数组的数据，写入到GIF文件中去
	 * 
	 * @param images
	 *            source images to put into GIF
	 * @param outputFileName
	 *            target file name
	 * @throws java.io.IOException
	 *             IOException
	 */
	public void writeGifFile(BufferedImage[] images, String outputFileName)
			throws IOException {
		Iterator imageWriters = ImageIO.getImageWritersBySuffix("GIF");
		if (!imageWriters.hasNext()) {
			throw new IOException("no ImageWriters for GIF");
		}
		ImageWriter imageWriter = (ImageWriter) imageWriters.next();
		File file = new File(outputFileName);
		file.delete();
		imageWriter.setOutput(ImageIO.createImageOutputStream(file));
		if (imageWriter.canWriteSequence()) {
			if (logger.isInfoEnabled()) {
				logger.info("Using writeToSequence for format GIF");
			}
			imageWriter.prepareWriteSequence(null);
			for (BufferedImage image : images) {
				imageWriter.writeToSequence(new IIOImage(image, null, null),
						null);
			}
			imageWriter.endWriteSequence();
		} else {
			if (logger.isInfoEnabled()) {
				logger.info("cross fingers for format GIF");
			}
			for (BufferedImage image : images) {
				imageWriter.write(image);
			}
		}
	}

	public static int getWidth(String fileName) {
		int width = 0;
		Image image;
		try {
			image = ImageIO.read(new File(fileName));
			width = image.getWidth(null);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return width;
	}

	public static int getHeight(String fileName) {
		int height = 0;
		Image image;
		try {
			image = ImageIO.read(new File(fileName));
			height = image.getHeight(null);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return height;
	}
}
